home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / williams.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  40KB  |  1,471 lines

  1. /***************************************************************************
  2.  
  3.   vidhrdw.c
  4.  
  5.   Functions to emulate the video hardware of the machine.
  6.  
  7. ***************************************************************************/
  8.  
  9. #ifndef WILLIAMS_BLITTERS
  10.  
  11.  
  12. #include "driver.h"
  13. #include "vidhrdw/generic.h"
  14.  
  15. /* globals from machine/williams.c */
  16. extern UINT8 williams2_bank;
  17. extern UINT16 sinistar_clip;
  18. extern UINT8 williams_cocktail;
  19.  
  20. /* RAM globals */
  21. UINT8 *williams_videoram;
  22. UINT8 *williams2_paletteram;
  23.  
  24. /* blitter variables */
  25. UINT8 *williams_blitterram;
  26. UINT8 williams_blitter_xor;
  27. UINT8 williams_blitter_remap;
  28. UINT8 williams_blitter_clip;
  29.  
  30. /* Blaster extra variables */
  31. UINT8 *blaster_video_bits;
  32. UINT8 *blaster_color_zero_table;
  33. UINT8 *blaster_color_zero_flags;
  34. static const UINT8 *blaster_remap;
  35. static UINT8 *blaster_remap_lookup;
  36. static UINT8 blaster_erase_screen;
  37. static UINT16 blaster_back_color;
  38.  
  39. /* tilemap variables */
  40. UINT8 williams2_tilemap_mask;
  41. const UINT8 *williams2_row_to_palette; /* take care of IC79 and J1/J2 */
  42. UINT8 williams2_M7_flip;
  43. INT8  williams2_videoshift;
  44. UINT8 williams2_special_bg_color;
  45. static UINT8 williams2_fg_color; /* IC90 */
  46. static UINT8 williams2_bg_color; /* IC89 */
  47.  
  48. /* later-Williams video control variables */
  49. UINT8 *williams2_blit_inhibit;
  50. UINT8 *williams2_xscroll_low;
  51. UINT8 *williams2_xscroll_high;
  52.  
  53. /* control routines */
  54. void williams2_vh_stop(void);
  55.  
  56. /* pixel copiers */
  57. static UINT8 *scanline_dirty;
  58. static void copy_pixels_8(struct osd_bitmap *bitmap, const struct rectangle *clip);
  59. static void copy_pixels_remap_8(struct osd_bitmap *bitmap, const struct rectangle *clip);
  60. static void copy_pixels_transparent_8(struct osd_bitmap *bitmap, const struct rectangle *clip);
  61. static void copy_pixels_16(struct osd_bitmap *bitmap, const struct rectangle *clip);
  62. static void copy_pixels_remap_16(struct osd_bitmap *bitmap, const struct rectangle *clip);
  63. static void copy_pixels_transparent_16(struct osd_bitmap *bitmap, const struct rectangle *clip);
  64.  
  65. /* blitter functions */
  66. static void williams_blit_opaque(int sstart, int dstart, int w, int h, int data);
  67. static void williams_blit_transparent(int sstart, int dstart, int w, int h, int data);
  68. static void williams_blit_opaque_solid(int sstart, int dstart, int w, int h, int data);
  69. static void williams_blit_transparent_solid(int sstart, int dstart, int w, int h, int data);
  70. static void sinistar_blit_opaque(int sstart, int dstart, int w, int h, int data);
  71. static void sinistar_blit_transparent(int sstart, int dstart, int w, int h, int data);
  72. static void sinistar_blit_opaque_solid(int sstart, int dstart, int w, int h, int data);
  73. static void sinistar_blit_transparent_solid(int sstart, int dstart, int w, int h, int data);
  74. static void blaster_blit_opaque(int sstart, int dstart, int w, int h, int data);
  75. static void blaster_blit_transparent(int sstart, int dstart, int w, int h, int data);
  76. static void blaster_blit_opaque_solid(int sstart, int dstart, int w, int h, int data);
  77. static void blaster_blit_transparent_solid(int sstart, int dstart, int w, int h, int data);
  78. static void williams2_blit_opaque(int sstart, int dstart, int w, int h, int data);
  79. static void williams2_blit_transparent(int sstart, int dstart, int w, int h, int data);
  80. static void williams2_blit_opaque_solid(int sstart, int dstart, int w, int h, int data);
  81. static void williams2_blit_transparent_solid(int sstart, int dstart, int w, int h, int data);
  82.  
  83. /* blitter tables */
  84. static void (**blitter_table)(int, int, int, int, int);
  85.  
  86. static void (*williams_blitters[])(int, int, int, int, int) =
  87. {
  88.     williams_blit_opaque,
  89.     williams_blit_transparent,
  90.     williams_blit_opaque_solid,
  91.     williams_blit_transparent_solid
  92. };
  93.  
  94. static void (*sinistar_blitters[])(int, int, int, int, int) =
  95. {
  96.     sinistar_blit_opaque,
  97.     sinistar_blit_transparent,
  98.     sinistar_blit_opaque_solid,
  99.     sinistar_blit_transparent_solid
  100. };
  101.  
  102. static void (*blaster_blitters[])(int, int, int, int, int) =
  103. {
  104.     blaster_blit_opaque,
  105.     blaster_blit_transparent,
  106.     blaster_blit_opaque_solid,
  107.     blaster_blit_transparent_solid
  108. };
  109.  
  110. static void (*williams2_blitters[])(int, int, int, int, int) =
  111. {
  112.     williams2_blit_opaque,
  113.     williams2_blit_transparent,
  114.     williams2_blit_opaque_solid,
  115.     williams2_blit_transparent_solid
  116. };
  117.  
  118.  
  119.  
  120. /*************************************
  121.  *
  122.  *    Dirty marking
  123.  *
  124.  *************************************/
  125.  
  126. static void mark_dirty(int x1, int y1, int x2, int y2)
  127. {
  128.     int temp;
  129.  
  130.     /* swap X/Y */
  131.     if (Machine->orientation & ORIENTATION_SWAP_XY)
  132.     {
  133.         temp = x1; x1 = y1; y1 = temp;
  134.         temp = x2; x2 = y2; y2 = temp;
  135.     }
  136.  
  137.     /* flip X */
  138.     if (Machine->orientation & ORIENTATION_FLIP_X)
  139.     {
  140.         temp = Machine->scrbitmap->width - 1;
  141.         x1 = temp - x1;
  142.         x2 = temp - x2;
  143.         temp = x1; x1 = x2; x2 = temp;
  144.     }
  145.  
  146.     /* flip Y */
  147.     if (Machine->orientation & ORIENTATION_FLIP_Y)
  148.     {
  149.         temp = Machine->scrbitmap->height - 1;
  150.         y1 = temp - y1;
  151.         y2 = temp - y2;
  152.         temp = y1; y1 = y2; y2 = temp;
  153.     }
  154.  
  155.     /* mark it */
  156.     osd_mark_dirty(x1, y1, x2, y2, 0);
  157. }
  158.  
  159.  
  160.  
  161. /*************************************
  162.  *
  163.  *    Early Williams video startup/shutdown
  164.  *
  165.  *************************************/
  166.  
  167. int williams_vh_start(void)
  168. {
  169.     /* allocate space for video RAM and dirty scanlines */
  170.     williams_videoram = malloc(videoram_size + 256);
  171.     if (!williams_videoram)
  172.         return 1;
  173.     scanline_dirty = williams_videoram + videoram_size;
  174.     memset(williams_videoram, 0, videoram_size);
  175.     memset(scanline_dirty, 1, 256);
  176.  
  177.     /* pick the blitters */
  178.     blitter_table = williams_blitters;
  179.     if (williams_blitter_remap) blitter_table = blaster_blitters;
  180.     if (williams_blitter_clip) blitter_table = sinistar_blitters;
  181.  
  182.     /* reset special-purpose flags */
  183.     blaster_remap_lookup = 0;
  184.     blaster_erase_screen = 0;
  185.     blaster_back_color = 0;
  186.     sinistar_clip = 0xffff;
  187.  
  188.     return 0;
  189. }
  190.  
  191.  
  192. void williams_vh_stop(void)
  193. {
  194.     /* free any remap lookup tables */
  195.     if (blaster_remap_lookup)
  196.         free(blaster_remap_lookup);
  197.     blaster_remap_lookup = NULL;
  198.  
  199.     /* free video RAM */
  200.     if (williams_videoram)
  201.         free(williams_videoram);
  202.     williams_videoram = NULL;
  203.     scanline_dirty = NULL;
  204. }
  205.  
  206.  
  207.  
  208. /*************************************
  209.  *
  210.  *    Early Williams video update
  211.  *
  212.  *************************************/
  213.  
  214. void williams_vh_update(int counter)
  215. {
  216.     struct rectangle clip;
  217.  
  218.     /* wrap around at the bottom */
  219.     if (counter == 0) counter = 256;
  220.  
  221.     /* determine the clip rect */
  222.     clip.min_x = Machine->drv->visible_area.min_x;
  223.     clip.max_x = Machine->drv->visible_area.max_x;
  224.     clip.min_y = counter - 16;
  225.     clip.max_y = clip.min_y + 15;
  226.  
  227.     /* combine the clip rect with the visible rect */
  228.     if (Machine->drv->visible_area.min_y > clip.min_y)
  229.         clip.min_y = Machine->drv->visible_area.min_y;
  230.     if (Machine->drv->visible_area.max_y < clip.max_y)
  231.         clip.max_y = Machine->drv->visible_area.max_y;
  232.  
  233.     /* copy */
  234.     if (Machine->scrbitmap->depth == 8)
  235.     {
  236.         if (williams_blitter_remap)
  237.             copy_pixels_remap_8(Machine->scrbitmap, &clip);
  238.         else
  239.             copy_pixels_8(Machine->scrbitmap, &clip);
  240.     }
  241.     else
  242.     {
  243.         if (williams_blitter_remap)
  244.             copy_pixels_remap_16(Machine->scrbitmap, &clip);
  245.         else
  246.             copy_pixels_16(Machine->scrbitmap, &clip);
  247.     }
  248.  
  249.     /* optionally erase from lines 24 downward */
  250.     if (blaster_erase_screen && clip.max_y > 24)
  251.     {
  252.         int offset, count;
  253.  
  254.         /* don't erase above row 24 */
  255.         if (clip.min_y < 24) clip.min_y = 24;
  256.  
  257.         /* erase the memory associated with this area */
  258.         count = clip.max_y - clip.min_y + 1;
  259.         for (offset = clip.min_y; offset < videoram_size; offset += 0x100)
  260.             memset(&williams_videoram[offset], 0, count);
  261.     }
  262. }
  263.  
  264.  
  265. void williams_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh)
  266. {
  267.     /* full refresh forces us to redraw everything */
  268.     if (palette_recalc() || full_refresh)
  269.         memset(scanline_dirty, 1, 256);
  270. }
  271.  
  272.  
  273.  
  274. /*************************************
  275.  *
  276.  *    Early Williams video I/O
  277.  *
  278.  *************************************/
  279.  
  280. WRITE_HANDLER( williams_videoram_w )
  281. {
  282.     /* only update if different */
  283.     if (williams_videoram[offset] != data)
  284.     {
  285.         /* store to videoram and mark the scanline dirty */
  286.         williams_videoram[offset] = data;
  287.         scanline_dirty[offset % 256] = 1;
  288.     }
  289. }
  290.  
  291.  
  292. READ_HANDLER( williams_video_counter_r )
  293. {
  294.     return cpu_getscanline() & 0xfc;
  295. }
  296.  
  297.  
  298.  
  299. /*************************************
  300.  *
  301.  *    Later Williams video startup/shutdown
  302.  *
  303.  *************************************/
  304.  
  305. int williams2_vh_start(void)
  306. {
  307.     /* standard initialization */
  308.     if (williams_vh_start())
  309.         return 1;
  310.  
  311.     /* override the blitters */
  312.     blitter_table = williams2_blitters;
  313.  
  314.     /* allocate a buffer for palette RAM */
  315.     williams2_paletteram = malloc(4 * 1024 * 4 / 8);
  316.     if (!williams2_paletteram)
  317.     {
  318.         williams2_vh_stop();
  319.         return 1;
  320.     }
  321.  
  322.     /* clear it */
  323.     memset(williams2_paletteram, 0, 4 * 1024 * 4 / 8);
  324.  
  325.     /* reset the FG/BG colors */
  326.     williams2_fg_color = 0;
  327.     williams2_bg_color = 0;
  328.  
  329.     return 0;
  330. }
  331.  
  332.  
  333. void williams2_vh_stop(void)
  334. {
  335.     /* free palette RAM */
  336.     if (williams2_paletteram)
  337.         free(williams2_paletteram);
  338.     williams2_paletteram = NULL;
  339.  
  340.     /* clean up other stuff */
  341.     williams_vh_stop();
  342. }
  343.  
  344.  
  345.  
  346. /*************************************
  347.  *
  348.  *    Later Williams video update
  349.  *
  350.  *************************************/
  351.  
  352. static void williams2_update_tiles(int y, const struct rectangle *clip)
  353. {
  354.     UINT8 *tileram = &memory_region(REGION_CPU1)[0xc000];
  355.     int xpixeloffset, xtileoffset;
  356.     int color, col;
  357.  
  358.     /* assemble the bits that describe the X scroll offset */
  359.     xpixeloffset = (*williams2_xscroll_high & 1) * 12 +
  360.                    (*williams2_xscroll_low >> 7) * 6 +
  361.                    (*williams2_xscroll_low & 7) +
  362.                    williams2_videoshift;
  363.     xtileoffset = *williams2_xscroll_high >> 1;
  364.  
  365.     /* adjust the offset for the row and compute the palette index */
  366.     tileram += y / 16;
  367.     color = williams2_row_to_palette[y / 16];
  368.  
  369.     /* 12 columns wide, each block is 24 pixels wide, 288 pixel lines */
  370.     for (col = 0; col <= 12; col++)
  371.     {
  372.         unsigned int map = tileram[((col + xtileoffset) * 16) & 0x07ff];
  373.  
  374.         drawgfx(Machine->scrbitmap, Machine->gfx[0], map & williams2_tilemap_mask,
  375.                 color, map & williams2_M7_flip, 0, col * 24 - xpixeloffset, y,
  376.                 &Machine->drv->visible_area, TRANSPARENCY_NONE, 0);
  377.     }
  378. }
  379.  
  380.  
  381. void williams2_vh_update(int counter)
  382. {
  383.     struct rectangle clip;
  384.  
  385.     /* wrap around at the bottom */
  386.     if (counter == 0) counter = 256;
  387.  
  388.     /* determine the clip rect */
  389.     clip.min_x = Machine->drv->visible_area.min_x;
  390.     clip.max_x = Machine->drv->visible_area.max_x;
  391.     clip.min_y = counter - 16;
  392.     clip.max_y = clip.min_y + 15;
  393.  
  394.     /* combine the clip rect with the visible rect */
  395.     if (Machine->drv->visible_area.min_y > clip.min_y)
  396.         clip.min_y = Machine->drv->visible_area.min_y;
  397.     if (Machine->drv->visible_area.max_y < clip.max_y)
  398.         clip.max_y = Machine->drv->visible_area.max_y;
  399.  
  400.     /* redraw the tiles */
  401.     williams2_update_tiles(counter - 16, &clip);
  402.  
  403.     /* copy the bitmap data on top of that */
  404.     if (Machine->scrbitmap->depth == 8)
  405.         copy_pixels_transparent_8(Machine->scrbitmap, &clip);
  406.     else
  407.         copy_pixels_transparent_16(Machine->scrbitmap, &clip);
  408. }
  409.  
  410.  
  411.  
  412. /*************************************
  413.  *
  414.  *    Later Williams palette I/O
  415.  *
  416.  *************************************/
  417.  
  418. static void williams2_modify_color(int color, int offset)
  419. {
  420.     static const UINT8 ztable[16] =
  421.     {
  422.         0x0, 0x3, 0x4,  0x5, 0x6, 0x7, 0x8,  0x9,
  423.         0xa, 0xb, 0xc,  0xd, 0xe, 0xf, 0x10, 0x11
  424.     };
  425.  
  426.     UINT8 entry_lo = williams2_paletteram[offset * 2];
  427.     UINT8 entry_hi = williams2_paletteram[offset * 2 + 1];
  428.     UINT8 i = ztable[(entry_hi >> 4) & 15];
  429.     UINT8 b = ((entry_hi >> 0) & 15) * i;
  430.     UINT8 g = ((entry_lo >> 4) & 15) * i;
  431.     UINT8 r = ((entry_lo >> 0) & 15) * i;
  432.  
  433.     palette_change_color(color, r, g, b);
  434. }
  435.  
  436.  
  437. static void williams2_update_fg_color(unsigned int offset)
  438. {
  439.     unsigned int page_offset = williams2_fg_color * 16;
  440.  
  441.     /* only modify the palette if we're talking to the current page */
  442.     if (offset >= page_offset && offset < page_offset + 16)
  443.         williams2_modify_color(offset - page_offset, offset);
  444. }
  445.  
  446.  
  447. static void williams2_update_bg_color(unsigned int offset)
  448. {
  449.     unsigned int page_offset = williams2_bg_color * 16;
  450.  
  451.     /* non-Mystic Marathon variant */
  452.     if (!williams2_special_bg_color)
  453.     {
  454.         /* only modify the palette if we're talking to the current page */
  455.         if (offset >= page_offset && offset < page_offset + Machine->drv->total_colors - 16)
  456.             williams2_modify_color(offset - page_offset + 16, offset);
  457.     }
  458.  
  459.     /* Mystic Marathon variant */
  460.     else
  461.     {
  462.         /* only modify the palette if we're talking to the current page */
  463.         if (offset >= page_offset && offset < page_offset + 16)
  464.             williams2_modify_color(offset - page_offset + 16, offset);
  465.  
  466.         /* check the secondary palette as well */
  467.         page_offset |= 0x10;
  468.         if (offset >= page_offset && offset < page_offset + 16)
  469.             williams2_modify_color(offset - page_offset + 32, offset);
  470.     }
  471. }
  472.  
  473.  
  474. WRITE_HANDLER( williams2_fg_select_w )
  475. {
  476.     unsigned int i, palindex;
  477.  
  478.     /* if we're already mapped, leave it alone */
  479.     if (williams2_fg_color == data)
  480.         return;
  481.     williams2_fg_color = data & 0x3f;
  482.  
  483.     /* remap the foreground colors */
  484.     palindex = williams2_fg_color * 16;
  485.     for (i = 0; i < 16; i++)
  486.         williams2_modify_color(i, palindex++);
  487. }
  488.  
  489.  
  490. WRITE_HANDLER( williams2_bg_select_w )
  491. {
  492.     unsigned int i, palindex;
  493.  
  494.     /* if we're already mapped, leave it alone */
  495.     if (williams2_bg_color == data)
  496.         return;
  497.     williams2_bg_color = data & 0x3f;
  498.  
  499.     /* non-Mystic Marathon variant */
  500.     if (!williams2_special_bg_color)
  501.     {
  502.         /* remap the background colors */
  503.         palindex = williams2_bg_color * 16;
  504.         for (i = 16; i < Machine->drv->total_colors; i++)
  505.             williams2_modify_color(i, palindex++);
  506.     }
  507.  
  508.     /* Mystic Marathon variant */
  509.     else
  510.     {
  511.         /* remap the background colors */
  512.         palindex = williams2_bg_color * 16;
  513.         for (i = 16; i < 32; i++)
  514.             williams2_modify_color(i, palindex++);
  515.  
  516.         /* remap the secondary background colors */
  517.         palindex = (williams2_bg_color | 1) * 16;
  518.         for (i = 32; i < 48; i++)
  519.             williams2_modify_color(i, palindex++);
  520.     }
  521. }
  522.  
  523.  
  524.  
  525. /*************************************
  526.  *
  527.  *    Later Williams video I/O
  528.  *
  529.  *************************************/
  530.  
  531. WRITE_HANDLER( williams2_videoram_w )
  532. {
  533.     /* bank 3 doesn't touch the screen */
  534.     if ((williams2_bank & 0x03) == 0x03)
  535.     {
  536.         /* bank 3 from $8000 - $8800 affects palette RAM */
  537.         if (offset >= 0x8000 && offset < 0x8800)
  538.         {
  539.             offset -= 0x8000;
  540.             williams2_paletteram[offset] = data;
  541.  
  542.             /* update the palette value if necessary */
  543.             offset >>= 1;
  544.             williams2_update_fg_color(offset);
  545.             williams2_update_bg_color(offset);
  546.         }
  547.         return;
  548.     }
  549.  
  550.     /* everyone else talks to the screen */
  551.     williams_videoram[offset] = data;
  552. }
  553.  
  554.  
  555.  
  556. /*************************************
  557.  *
  558.  *    Blaster-specific video start
  559.  *
  560.  *************************************/
  561.  
  562. int blaster_vh_start(void)
  563. {
  564.     int i, j;
  565.  
  566.     /* standard startup first */
  567.     if (williams_vh_start())
  568.         return 1;
  569.  
  570.     /* Expand the lookup table so that we do one lookup per byte */
  571.     blaster_remap_lookup = malloc(256 * 256);
  572.     if (blaster_remap_lookup)
  573.         for (i = 0; i < 256; i++)
  574.         {
  575.             const UINT8 *table = memory_region(REGION_PROMS) + (i & 0x7f) * 16;
  576.             for (j = 0; j < 256; j++)
  577.                 blaster_remap_lookup[i * 256 + j] = (table[j >> 4] << 4) | table[j & 0x0f];
  578.         }
  579.  
  580.     /* mark color 0 as transparent. we will draw the rainbow background behind it */
  581.     palette_used_colors[0] = PALETTE_COLOR_TRANSPARENT;
  582.     for (i = 0; i < 256; i++)
  583.     {
  584.         /* mark as used only the colors used for the visible background lines */
  585.         if (i < Machine->drv->visible_area.min_y || i > Machine->drv->visible_area.max_y)
  586.             palette_used_colors[16 + i] = PALETTE_COLOR_UNUSED;
  587.  
  588.         /* TODO: this leaves us with a total of 255+1 colors used, which is just */
  589.         /* a bit too much for the palette system to handle them efficiently. */
  590.         /* As a quick workaround, I set the top three lines to be always black. */
  591.         /* To do it correctly, vh_screenrefresh() should group the background */
  592.         /* lines of the same color and mark the others as COLOR_UNUSED. */
  593.         /* The background is very redundant so this can be done easily. */
  594.         palette_used_colors[16 + 0 + Machine->drv->visible_area.min_y] = PALETTE_COLOR_TRANSPARENT;
  595.         palette_used_colors[16 + 1 + Machine->drv->visible_area.min_y] = PALETTE_COLOR_TRANSPARENT;
  596.         palette_used_colors[16 + 2 + Machine->drv->visible_area.min_y] = PALETTE_COLOR_TRANSPARENT;
  597.     }
  598.  
  599.     return 0;
  600. }
  601.  
  602.  
  603.  
  604. /*************************************
  605.  *
  606.  *    Blaster-specific video refresh
  607.  *
  608.  *************************************/
  609.  
  610. void blaster_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh)
  611. {
  612.     int j;
  613.  
  614.     /* recalculate palette -- unfortunately, there is no recourse if a */
  615.     /* major change occurs; we'll just have to eat it for one frame    */
  616.     for (j = 0; j < 0x100; j++)
  617.         paletteram_BBGGGRRR_w(j + 16, blaster_color_zero_table[j] ^ 0xff);
  618.     palette_recalc();
  619.  
  620.     /* reset the background color for the next frame */
  621.     blaster_back_color = 0;
  622. }
  623.  
  624.  
  625.  
  626. /*************************************
  627.  *
  628.  *    Blaster-specific enhancements
  629.  *
  630.  *************************************/
  631.  
  632. WRITE_HANDLER( blaster_remap_select_w )
  633. {
  634.     blaster_remap = blaster_remap_lookup + data * 256;
  635. }
  636.  
  637.  
  638. WRITE_HANDLER( blaster_video_bits_w )
  639. {
  640.     *blaster_video_bits = data;
  641.     blaster_erase_screen = data & 0x02;
  642. }
  643.  
  644.  
  645.  
  646. /*************************************
  647.  *
  648.  *    Blitter core
  649.  *
  650.  *************************************/
  651.  
  652. /*
  653.  
  654.     Blitter description from Sean Riddle's page:
  655.  
  656.     This page contains information about the Williams Special Chips, which
  657.     were 'bit blitters'- block transfer chips that could move data around on
  658.     the screen and in memory faster than the CPU. In fact, I've timed the
  659.     special chips at 16 megs in 18.1 seconds. That's 910K/sec, not bad for
  660.     the early 80s.
  661.  
  662.     The blitters were not used in Defender and Stargate, but
  663.     were added to the ROM boards of the later games. Splat!, Blaster, Mystic
  664.     Marathon and Joust 2 used Special Chip 2s. The only difference that I've
  665.     seen is that SC1s have a small bug. When you tell the SC1 the size of
  666.     the data to move, you have to exclusive-or the width and height with 2.
  667.     The SC2s eliminate this bug.
  668.  
  669.     The blitters were accessed at memory location $CA00-CA06.
  670.  
  671.     CA01 is the mask, usually $FF to move all bits.
  672.     CA02-3 is the source data location.
  673.     CA04-5 is the destination data location.
  674.  
  675.     Writing to CA00 starts the blit, and the byte written determines how the
  676.     data is blitted.
  677.  
  678.     Bit 0 indicates that the source data is either laid out linear, one
  679.     pixel after the last, or in screen format, where there are 256 bytes from
  680.     one pair of pixels to the next.
  681.  
  682.     Bit 1 indicates the same, but for the destination data.
  683.  
  684.     I'm not sure what bit 2 does. Looking at the image, I can't tell, but
  685.     perhaps it has to do with the mask. My test files only used a mask of $FF.
  686.  
  687.     Bit 3 tells the blitter only to blit the foreground- that is, everything
  688.     that is not color 0. Also known as transparency mode.
  689.  
  690.     Bit 4 is 'solid' mode. Only the color indicated by the mask is blitted.
  691.     Note that this just creates a rectangle unless bit 3 is also set, in which
  692.     case it blits the image, but in a solid color.
  693.  
  694.     Bit 5 shifts the image one pixel to the right. Any data on the far right
  695.     jumps to the far left.
  696.  
  697.     Bits 6 and 7 only blit every other pixel of the image. Bit 6 says even only,
  698.     while bit 7 says odd only.
  699.  
  700. */
  701.  
  702.  
  703.  
  704. /*************************************
  705.  *
  706.  *    Blitter I/O
  707.  *
  708.  *************************************/
  709.  
  710. WRITE_HANDLER( williams_blitter_w )
  711. {
  712.     int sstart, dstart, w, h, count;
  713.  
  714.     /* store the data */
  715.     williams_blitterram[offset] = data;
  716.  
  717.     /* only writes to location 0 trigger the blit */
  718.     if (offset != 0)
  719.         return;
  720.  
  721.     /* compute the starting locations */
  722.     sstart = (williams_blitterram[2] << 8) + williams_blitterram[3];
  723.     dstart = (williams_blitterram[4] << 8) + williams_blitterram[5];
  724.  
  725.     /* compute the width and height */
  726.     w = williams_blitterram[6] ^ williams_blitter_xor;
  727.     h = williams_blitterram[7] ^ williams_blitter_xor;
  728.  
  729.     /* adjust the width and height */
  730.     if (w == 0) w = 1;
  731.     if (h == 0) h = 1;
  732.     if (w == 255) w = 256;
  733.     if (h == 255) h = 256;
  734.  
  735.     /* call the appropriate blitter */
  736.     (*blitter_table[(data >> 3) & 3])(sstart, dstart, w, h, data);
  737.  
  738.     /* compute the ending address */
  739.     if (data & 0x02)
  740.         count = h;
  741.     else
  742.         count = w + w * h;
  743.     if (count > 256) count = 256;
  744.  
  745.     /* mark dirty */
  746.     w = dstart % 256;
  747.     while (count-- > 0)
  748.         scanline_dirty[w++ % 256] = 1;
  749.  
  750.     /* Log blits */
  751.     logerror("---------- Blit %02X--------------PC: %04X\n",data,cpu_get_pc());
  752.     logerror("Source : %02X %02X\n",williams_blitterram[2],williams_blitterram[3]);
  753.     logerror("Dest   : %02X %02X\n",williams_blitterram[4],williams_blitterram[5]);
  754.     logerror("W H    : %02X %02X (%d,%d)\n",williams_blitterram[6],williams_blitterram[7],williams_blitterram[6]^4,williams_blitterram[7]^4);
  755.     logerror("Mask   : %02X\n",williams_blitterram[1]);
  756. }
  757.  
  758.  
  759.  
  760. /*************************************
  761.  *
  762.  *    Blitter macros
  763.  *
  764.  *************************************/
  765.  
  766. /* blit with pixel color 0 == transparent */
  767. #define BLIT_TRANSPARENT(offset, data, keepmask)        \
  768. {                                                        \
  769.     data = REMAP(data);                                    \
  770.     if (data)                                            \
  771.     {                                                    \
  772.         int pix = BLITTER_DEST_READ(offset);            \
  773.         int tempmask = keepmask;                        \
  774.                                                         \
  775.         if (!(data & 0xf0)) tempmask |= 0xf0;            \
  776.         if (!(data & 0x0f)) tempmask |= 0x0f;            \
  777.                                                         \
  778.         pix = (pix & tempmask) | (data & ~tempmask);    \
  779.         BLITTER_DEST_WRITE(offset, pix);                \
  780.     }                                                    \
  781. }
  782.  
  783. /* blit with pixel color 0 == transparent, other pixels == solid color */
  784. #define BLIT_TRANSPARENT_SOLID(offset, data, keepmask)    \
  785. {                                                        \
  786.     data = REMAP(data);                                    \
  787.     if (data)                                            \
  788.     {                                                    \
  789.         int pix = BLITTER_DEST_READ(offset);            \
  790.         int tempmask = keepmask;                        \
  791.                                                         \
  792.         if (!(data & 0xf0)) tempmask |= 0xf0;            \
  793.         if (!(data & 0x0f)) tempmask |= 0x0f;            \
  794.                                                         \
  795.         pix = (pix & tempmask) | (solid & ~tempmask);    \
  796.         BLITTER_DEST_WRITE(offset, pix);                \
  797.     }                                                    \
  798. }
  799.  
  800. /* blit with no transparency */
  801. #define BLIT_OPAQUE(offset, data, keepmask)                \
  802. {                                                        \
  803.     int pix = BLITTER_DEST_READ(offset);                \
  804.     data = REMAP(data);                                    \
  805.     pix = (pix & keepmask) | (data & ~keepmask);        \
  806.     BLITTER_DEST_WRITE(offset, pix);                    \
  807. }
  808.  
  809. /* blit with no transparency in a solid color */
  810. #define BLIT_OPAQUE_SOLID(offset, data, keepmask)        \
  811. {                                                        \
  812.     int pix = BLITTER_DEST_READ(offset);                \
  813.     pix = (pix & keepmask) | (solid & ~keepmask);        \
  814.     BLITTER_DEST_WRITE(offset, pix);                    \
  815.     (void)srcdata;    /* keeps compiler happy */            \
  816. }
  817.  
  818.  
  819. /* early Williams blitters */
  820. #define WILLIAMS_DEST_WRITE(d,v)        if (d < 0x9800) williams_videoram[d] = v; else cpu_writemem16(d, v)
  821. #define WILLIAMS_DEST_READ(d)            ((d < 0x9800) ? williams_videoram[d] : cpu_readmem16(d))
  822.  
  823. /* Sinistar blitter checks clipping circuit */
  824. #define SINISTAR_DEST_WRITE(d,v)        if (d < sinistar_clip) { if (d < 0x9800) williams_videoram[d] = v; else cpu_writemem16(d, v); }
  825. #define SINISTAR_DEST_READ(d)            ((d < 0x9800) ? williams_videoram[d] : cpu_readmem16(d))
  826.  
  827. /* Blaster blitter remaps through a lookup table */
  828. #define BLASTER_DEST_WRITE(d,v)            if (d < 0x9700) williams_videoram[d] = v; else cpu_writemem16(d, v)
  829. #define BLASTER_DEST_READ(d)            ((d < 0x9700) ? williams_videoram[d] : cpu_readmem16(d))
  830.  
  831. /* later Williams blitters */
  832. #define WILLIAMS2_DEST_WRITE(d,v)        if (d < 0x9000 && (williams2_bank & 0x03) != 0x03) williams_videoram[d] = v; else if (d < 0x9000 || d >= 0xc000 || *williams2_blit_inhibit == 0) cpu_writemem16(d, v)
  833. #define WILLIAMS2_DEST_READ(d)            ((d < 0x9000 && (williams2_bank & 0x03) != 0x03) ? williams_videoram[d] : cpu_readmem16(d))
  834.  
  835. /* to remap or not remap */
  836. #define REMAP_FUNC(r)                    blaster_remap[(r) & 0xff]
  837. #define NOREMAP_FUNC(r)                    (r)
  838.  
  839. /* define this so that we get the blitter code when we #include ourself */
  840. #define WILLIAMS_BLITTERS                1
  841.  
  842.  
  843. /**************** original williams blitters ****************/
  844. #define BLITTER_DEST_WRITE                WILLIAMS_DEST_WRITE
  845. #define BLITTER_DEST_READ                WILLIAMS_DEST_READ
  846. #define REMAP                             NOREMAP_FUNC
  847.  
  848. #define BLITTER_OP                         BLIT_TRANSPARENT
  849. #define BLITTER_NAME                    williams_blit_transparent
  850. #include "williams.c"
  851. #undef BLITTER_NAME
  852. #undef BLITTER_OP
  853.  
  854. #define BLITTER_OP                         BLIT_TRANSPARENT_SOLID
  855. #define BLITTER_NAME                    williams_blit_transparent_solid
  856. #include "williams.c"
  857. #undef BLITTER_NAME
  858. #undef BLITTER_OP
  859.  
  860. #define BLITTER_OP                         BLIT_OPAQUE
  861. #define BLITTER_NAME                    williams_blit_opaque
  862. #include "williams.c"
  863. #undef BLITTER_NAME
  864. #undef BLITTER_OP
  865.  
  866. #define BLITTER_OP                         BLIT_OPAQUE_SOLID
  867. #define BLITTER_NAME                    williams_blit_opaque_solid
  868. #include "williams.c"
  869. #undef BLITTER_NAME
  870. #undef BLITTER_OP
  871.  
  872. #undef REMAP
  873. #undef BLITTER_DEST_WRITE
  874. #undef BLITTER_DEST_READ
  875.  
  876.  
  877. /**************** Sinistar-specific (clipping) blitters ****************/
  878. #define BLITTER_DEST_WRITE                SINISTAR_DEST_WRITE
  879. #define BLITTER_DEST_READ                SINISTAR_DEST_READ
  880. #define REMAP                             NOREMAP_FUNC
  881.  
  882. #define BLITTER_OP                         BLIT_TRANSPARENT
  883. #define BLITTER_NAME                    sinistar_blit_transparent
  884. #include "williams.c"
  885. #undef BLITTER_NAME
  886. #undef BLITTER_OP
  887.  
  888. #define BLITTER_OP                         BLIT_TRANSPARENT_SOLID
  889. #define BLITTER_NAME                    sinistar_blit_transparent_solid
  890. #include "williams.c"
  891. #undef BLITTER_NAME
  892. #undef BLITTER_OP
  893.  
  894. #define BLITTER_OP                         BLIT_OPAQUE
  895. #define BLITTER_NAME                    sinistar_blit_opaque
  896. #include "williams.c"
  897. #undef BLITTER_NAME
  898. #undef BLITTER_OP
  899.  
  900. #define BLITTER_OP                         BLIT_OPAQUE_SOLID
  901. #define BLITTER_NAME                    sinistar_blit_opaque_solid
  902. #include "williams.c"
  903. #undef BLITTER_NAME
  904. #undef BLITTER_OP
  905.  
  906. #undef REMAP
  907. #undef BLITTER_DEST_WRITE
  908. #undef BLITTER_DEST_READ
  909.  
  910.  
  911. /**************** Blaster-specific (remapping) blitters ****************/
  912. #define BLITTER_DEST_WRITE                BLASTER_DEST_WRITE
  913. #define BLITTER_DEST_READ                BLASTER_DEST_READ
  914. #define REMAP                             REMAP_FUNC
  915.  
  916. #define BLITTER_OP                         BLIT_TRANSPARENT
  917. #define BLITTER_NAME                    blaster_blit_transparent
  918. #include "williams.c"
  919. #undef BLITTER_NAME
  920. #undef BLITTER_OP
  921.  
  922. #define BLITTER_OP                         BLIT_TRANSPARENT_SOLID
  923. #define BLITTER_NAME                    blaster_blit_transparent_solid
  924. #include "williams.c"
  925. #undef BLITTER_NAME
  926. #undef BLITTER_OP
  927.  
  928. #define BLITTER_OP                         BLIT_OPAQUE
  929. #define BLITTER_NAME                    blaster_blit_opaque
  930. #include "williams.c"
  931. #undef BLITTER_NAME
  932. #undef BLITTER_OP
  933.  
  934. #define BLITTER_OP                         BLIT_OPAQUE_SOLID
  935. #define BLITTER_NAME                    blaster_blit_opaque_solid
  936. #include "williams.c"
  937. #undef BLITTER_NAME
  938. #undef BLITTER_OP
  939.  
  940. #undef REMAP
  941. #undef BLITTER_DEST_WRITE
  942. #undef BLITTER_DEST_READ
  943.  
  944.  
  945. /**************** Williams2-specific blitters ****************/
  946. #define BLITTER_DEST_WRITE                WILLIAMS2_DEST_WRITE
  947. #define BLITTER_DEST_READ                WILLIAMS2_DEST_READ
  948. #define REMAP                             NOREMAP_FUNC
  949.  
  950. #define BLITTER_OP                         BLIT_TRANSPARENT
  951. #define BLITTER_NAME                    williams2_blit_transparent
  952. #include "williams.c"
  953. #undef BLITTER_NAME
  954. #undef BLITTER_OP
  955.  
  956. #define BLITTER_OP                         BLIT_TRANSPARENT_SOLID
  957. #define BLITTER_NAME                    williams2_blit_transparent_solid
  958. #include "williams.c"
  959. #undef BLITTER_NAME
  960. #undef BLITTER_OP
  961.  
  962. #define BLITTER_OP                         BLIT_OPAQUE
  963. #define BLITTER_NAME                    williams2_blit_opaque
  964. #include "williams.c"
  965. #undef BLITTER_NAME
  966. #undef BLITTER_OP
  967.  
  968. #define BLITTER_OP                         BLIT_OPAQUE_SOLID
  969. #define BLITTER_NAME                    williams2_blit_opaque_solid
  970. #include "williams.c"
  971. #undef BLITTER_NAME
  972. #undef BLITTER_OP
  973.  
  974. #undef REMAP
  975. #undef BLITTER_DEST_WRITE
  976. #undef BLITTER_DEST_READ
  977.  
  978.  
  979.  
  980. /*************************************
  981.  *
  982.  *    Pixel copy macros
  983.  *
  984.  *************************************/
  985.  
  986. /* define this so that we get the pixel copying code when we #include ourself */
  987. #define WILLIAMS_COPIES                 1
  988.  
  989. #define COPY_NAME                         copy_pixels_8
  990. #define COPY_REMAP_NAME                    copy_pixels_remap_8
  991. #define COPY_TRANSPARENT_NAME            copy_pixels_transparent_8
  992. #define TYPE                            UINT8
  993. #include "williams.c"
  994. #undef TYPE
  995. #undef COPY_TRANSPARENT_NAME
  996. #undef COPY_REMAP_NAME
  997. #undef COPY_NAME
  998.  
  999. #define COPY_NAME                         copy_pixels_16
  1000. #define COPY_REMAP_NAME                    copy_pixels_remap_16
  1001. #define COPY_TRANSPARENT_NAME            copy_pixels_transparent_16
  1002. #define TYPE                            UINT16
  1003. #include "williams.c"
  1004. #undef TYPE
  1005. #undef COPY_TRANSPARENT_NAME
  1006. #undef COPY_REMAP_NAME
  1007. #undef COPY_NAME
  1008.  
  1009.  
  1010.  
  1011. #elif !defined(WILLIAMS_COPIES)
  1012.  
  1013.  
  1014.  
  1015. /*************************************
  1016.  *
  1017.  *    Blitter cores
  1018.  *
  1019.  *************************************/
  1020.  
  1021. static void BLITTER_NAME(int sstart, int dstart, int w, int h, int data)
  1022. {
  1023.     int source, sxadv, syadv;
  1024.     int dest, dxadv, dyadv;
  1025.     int i, j, solid;
  1026.     int keepmask;
  1027.  
  1028.     /* compute how much to advance in the x and y loops */
  1029.     sxadv = (data & 0x01) ? 0x100 : 1;
  1030.     syadv = (data & 0x01) ? 1 : w;
  1031.     dxadv = (data & 0x02) ? 0x100 : 1;
  1032.     dyadv = (data & 0x02) ? 1 : w;
  1033.  
  1034.     /* determine the common mask */
  1035.     keepmask = 0x00;
  1036.     if (data & 0x80) keepmask |= 0xf0;
  1037.     if (data & 0x40) keepmask |= 0x0f;
  1038.     if (keepmask == 0xff)
  1039.         return;
  1040.  
  1041.     /* set the solid pixel value to the mask value */
  1042.     solid = williams_blitterram[1];
  1043.  
  1044.     /* first case: no shifting */
  1045.     if (!(data & 0x20))
  1046.     {
  1047.         /* loop over the height */
  1048.         for (i = 0; i < h; i++)
  1049.         {
  1050.             source = sstart & 0xffff;
  1051.             dest = dstart & 0xffff;
  1052.  
  1053.             /* loop over the width */
  1054.             for (j = w; j > 0; j--)
  1055.             {
  1056.                 int srcdata = cpu_readmem16(source);
  1057.                 BLITTER_OP(dest, srcdata, keepmask);
  1058.  
  1059.                 source = (source + sxadv) & 0xffff;
  1060.                 dest   = (dest + dxadv) & 0xffff;
  1061.             }
  1062.  
  1063.             sstart += syadv;
  1064.             dstart += dyadv;
  1065.         }
  1066.     }
  1067.     /* second case: shifted one pixel */
  1068.     else
  1069.     {
  1070.         /* swap halves of the keep mask and the solid color */
  1071.         keepmask = ((keepmask & 0xf0) >> 4) | ((keepmask & 0x0f) << 4);
  1072.         solid = ((solid & 0xf0) >> 4) | ((solid & 0x0f) << 4);
  1073.  
  1074.         /* loop over the height */
  1075.         for (i = 0; i < h; i++)
  1076.         {
  1077.             int pixdata, srcdata, shiftedmask;
  1078.  
  1079.             source = sstart & 0xffff;
  1080.             dest = dstart & 0xffff;
  1081.  
  1082.             /* left edge case */
  1083.             pixdata = cpu_readmem16(source);
  1084.             srcdata = (pixdata >> 4) & 0x0f;
  1085.             shiftedmask = keepmask | 0xf0;
  1086.             BLITTER_OP(dest, srcdata, shiftedmask);
  1087.  
  1088.             source = (source + sxadv) & 0xffff;
  1089.             dest   = (dest + dxadv) & 0xffff;
  1090.  
  1091.             /* loop over the width */
  1092.             for (j = w - 1; j > 0; j--)
  1093.             {
  1094.                 pixdata = (pixdata << 8) | cpu_readmem16(source);
  1095.                 srcdata = (pixdata >> 4) & 0xff;
  1096.                 BLITTER_OP(dest, srcdata, keepmask);
  1097.  
  1098.                 source = (source + sxadv) & 0xffff;
  1099.                 dest   = (dest + dxadv) & 0xffff;
  1100.             }
  1101.  
  1102.             /* right edge case */
  1103.             srcdata = (pixdata << 4) & 0xf0;
  1104.             shiftedmask = keepmask | 0x0f;
  1105.             BLITTER_OP(dest, srcdata, shiftedmask);
  1106.  
  1107.             sstart += syadv;
  1108.             dstart += dyadv;
  1109.         }
  1110.     }
  1111. }
  1112.  
  1113.  
  1114. #else
  1115.  
  1116.  
  1117. /*************************************
  1118.  *
  1119.  *    Copy pixels from videoram to
  1120.  *    the screen bitmap
  1121.  *
  1122.  *************************************/
  1123.  
  1124. static void COPY_NAME(struct osd_bitmap *bitmap, const struct rectangle *clip)
  1125. {
  1126.     const UINT16 *pens = Machine->pens;
  1127.     int pairs = (clip->max_x - clip->min_x + 1) / 2;
  1128.     int xoffset = clip->min_x;
  1129.     int x, y;
  1130.  
  1131.     /* standard case */
  1132.     if (!(Machine->orientation & ORIENTATION_SWAP_XY))
  1133.     {
  1134.         /* loop over rows */
  1135.         for (y = clip->min_y; y <= clip->max_y; y++)
  1136.         {
  1137.             const UINT8 *source = williams_videoram + y + 256 * (xoffset / 2);
  1138.             TYPE *dest;
  1139.  
  1140.             /* skip if not dirty */
  1141.             if (!scanline_dirty[y]) continue;
  1142.             scanline_dirty[y] = 0;
  1143.             mark_dirty(clip->min_x, y, clip->max_x, y);
  1144.  
  1145.             /* compute starting destination pixel based on flip */
  1146.             if (!(Machine->orientation & ORIENTATION_FLIP_Y))
  1147.                 dest = &((TYPE *)bitmap->line[y])[0];
  1148.             else
  1149.                 dest = &((TYPE *)bitmap->line[bitmap->height - 1 - y])[0];
  1150.  
  1151.             /* non-X-flipped case */
  1152.             if (!(Machine->orientation & ORIENTATION_FLIP_X))
  1153.             {
  1154.                 dest += xoffset;
  1155.                 for (x = 0; x < pairs; x++, source += 256, dest += 2)
  1156.                 {
  1157.                     int pix = *source;
  1158.                     dest[0] = pens[pix >> 4];
  1159.                     dest[1] = pens[pix & 0x0f];
  1160.                 }
  1161.             }
  1162.  
  1163.             /* X-flipped case */
  1164.             else
  1165.             {
  1166.                 dest += bitmap->width - xoffset;
  1167.                 for (x = 0; x < pairs; x++, source += 256, dest -= 2)
  1168.                 {
  1169.                     int pix = *source;
  1170.                     dest[-1] = pens[pix >> 4];
  1171.                     dest[-2] = pens[pix & 0x0f];
  1172.                 }
  1173.             }
  1174.         }
  1175.     }
  1176.  
  1177.     /* X/Y swapped case */
  1178.     else
  1179.     {
  1180.         int dy = (bitmap->line[1] - bitmap->line[0]) / sizeof(TYPE);
  1181.  
  1182.         /* loop over rows */
  1183.         for (y = clip->min_y; y <= clip->max_y; y++)
  1184.         {
  1185.             const UINT8 *source = williams_videoram + y + 256 * (xoffset / 2);
  1186.             TYPE *dest;
  1187.  
  1188.             /* skip if not dirty */
  1189.             if (!scanline_dirty[y]) continue;
  1190.             scanline_dirty[y] = 0;
  1191.             mark_dirty(clip->min_x, y, clip->max_x, y);
  1192.  
  1193.             /* compute starting destination pixel based on flip */
  1194.             if (!(Machine->orientation & ORIENTATION_FLIP_X))
  1195.                 dest = &((TYPE *)bitmap->line[0])[y];
  1196.             else
  1197.                 dest = &((TYPE *)bitmap->line[0])[bitmap->width - 1 - y];
  1198.  
  1199.             /* non-Y-flipped case */
  1200.             if (!(Machine->orientation & ORIENTATION_FLIP_Y))
  1201.             {
  1202.                 dest += xoffset * dy;
  1203.                 for (x = 0; x < pairs; x++, source += 256, dest += dy + dy)
  1204.                 {
  1205.                     int pix = *source;
  1206.                     dest[0] = pens[pix >> 4];
  1207.                     dest[dy] = pens[pix & 0x0f];
  1208.                 }
  1209.             }
  1210.  
  1211.             /* Y-flipped case */
  1212.             else
  1213.             {
  1214.                 dest += (bitmap->height - xoffset) * dy;
  1215.                 for (x = 0; x < pairs; x++, source += 256, dest -= dy + dy)
  1216.                 {
  1217.                     int pix = *source;
  1218.                     dest[-dy] = pens[pix >> 4];
  1219.                     dest[-dy-dy] = pens[pix & 0x0f];
  1220.                 }
  1221.             }
  1222.         }
  1223.     }
  1224. }
  1225.  
  1226.  
  1227.  
  1228. /*************************************
  1229.  *
  1230.  *    Copy pixels from videoram to
  1231.  *    the screen bitmap, handling
  1232.  *    Blaster's color 0 latching
  1233.  *
  1234.  *************************************/
  1235.  
  1236. static void COPY_REMAP_NAME(struct osd_bitmap *bitmap, const struct rectangle *clip)
  1237. {
  1238.     int pairs = (clip->max_x - clip->min_x + 1) / 2;
  1239.     int xoffset = clip->min_x;
  1240.     UINT16 pens[16];
  1241.     int x, y;
  1242.  
  1243.     /* copy the pens to start */
  1244.     memcpy(pens, Machine->pens, sizeof(pens));
  1245.  
  1246.     /* standard case */
  1247.     if (!(Machine->orientation & ORIENTATION_SWAP_XY))
  1248.     {
  1249.         /* loop over rows */
  1250.         for (y = clip->min_y; y <= clip->max_y; y++)
  1251.         {
  1252.             const UINT8 *source = williams_videoram + y + 256 * (xoffset / 2);
  1253.             TYPE *dest;
  1254.  
  1255.             /* pick the background pen */
  1256.             if (*blaster_video_bits & 1)
  1257.             {
  1258.                 if (blaster_color_zero_flags[y] & 1)
  1259.                     blaster_back_color = (blaster_color_zero_table[y] != 0xff) ? 16 + y : 0;
  1260.             }
  1261.             else
  1262.                 blaster_back_color = 0;
  1263.             pens[0] = Machine->pens[blaster_back_color];
  1264.  
  1265.             /* compute starting destination pixel based on flip */
  1266.             if (!(Machine->orientation & ORIENTATION_FLIP_Y))
  1267.                 dest = &((TYPE *)bitmap->line[y])[0];
  1268.             else
  1269.                 dest = &((TYPE *)bitmap->line[bitmap->height - 1 - y])[0];
  1270.  
  1271.             /* non-X-flipped case */
  1272.             if (!(Machine->orientation & ORIENTATION_FLIP_X))
  1273.             {
  1274.                 dest += xoffset;
  1275.                 for (x = 0; x < pairs; x++, source += 256, dest += 2)
  1276.                 {
  1277.                     int pix = *source;
  1278.                     dest[0] = pens[pix >> 4];
  1279.                     dest[1] = pens[pix & 0x0f];
  1280.                 }
  1281.             }
  1282.  
  1283.             /* X-flipped case */
  1284.             else
  1285.             {
  1286.                 dest += bitmap->width - xoffset;
  1287.                 for (x = 0; x < pairs; x++, source += 256, dest -= 2)
  1288.                 {
  1289.                     int pix = *source;
  1290.                     dest[-1] = pens[pix >> 4];
  1291.                     dest[-2] = pens[pix & 0x0f];
  1292.                 }
  1293.             }
  1294.         }
  1295.     }
  1296.  
  1297.     /* X/Y swapped case */
  1298.     else
  1299.     {
  1300.         int dy = (bitmap->line[1] - bitmap->line[0]) / sizeof(TYPE);
  1301.  
  1302.         /* loop over rows */
  1303.         for (y = clip->min_y; y <= clip->max_y; y++)
  1304.         {
  1305.             const UINT8 *source = williams_videoram + y + 256 * (xoffset / 2);
  1306.             TYPE *dest;
  1307.  
  1308.             /* pick the background pen */
  1309.             if (*blaster_video_bits & 1)
  1310.             {
  1311.                 if (blaster_color_zero_flags[y] & 1)
  1312.                     blaster_back_color = (blaster_color_zero_table[y] != 0xff) ? 16 + y : 0;
  1313.             }
  1314.             else
  1315.                 blaster_back_color = 0;
  1316.             pens[0] = Machine->pens[blaster_back_color];
  1317.  
  1318.             /* compute starting destination pixel based on flip */
  1319.             if (!(Machine->orientation & ORIENTATION_FLIP_X))
  1320.                 dest = &((TYPE *)bitmap->line[0])[y];
  1321.             else
  1322.                 dest = &((TYPE *)bitmap->line[0])[bitmap->width - 1 - y];
  1323.  
  1324.             /* non-Y-flipped case */
  1325.             if (!(Machine->orientation & ORIENTATION_FLIP_Y))
  1326.             {
  1327.                 dest += xoffset * dy;
  1328.                 for (x = 0; x < pairs; x++, source += 256, dest += dy + dy)
  1329.                 {
  1330.                     int pix = *source;
  1331.                     dest[0] = pens[pix >> 4];
  1332.                     dest[dy] = pens[pix & 0x0f];
  1333.                 }
  1334.             }
  1335.  
  1336.             /* Y-flipped case */
  1337.             else
  1338.             {
  1339.                 dest += (bitmap->height - xoffset) * dy;
  1340.                 for (x = 0; x < pairs; x++, source += 256, dest -= dy + dy)
  1341.                 {
  1342.                     int pix = *source;
  1343.                     dest[-dy] = pens[pix >> 4];
  1344.                     dest[-dy-dy] = pens[pix & 0x0f];
  1345.                 }
  1346.             }
  1347.         }
  1348.     }
  1349. }
  1350.  
  1351.  
  1352.  
  1353. /*************************************
  1354.  *
  1355.  *    Copy pixels from videoram to
  1356.  *    the screen bitmap, treating
  1357.  *    color 0 pixels as transparent.
  1358.  *
  1359.  *************************************/
  1360.  
  1361. static void COPY_TRANSPARENT_NAME(struct osd_bitmap *bitmap, const struct rectangle *clip)
  1362. {
  1363.     const UINT16 *pens = Machine->pens;
  1364.     int pairs = (clip->max_x - clip->min_x + 1) / 2;
  1365.     int xoffset = clip->min_x;
  1366.     int x, y;
  1367.  
  1368.     /* standard case */
  1369.     if (!(Machine->orientation & ORIENTATION_SWAP_XY))
  1370.     {
  1371.         /* loop over rows */
  1372.         for (y = clip->min_y; y <= clip->max_y; y++)
  1373.         {
  1374.             const UINT8 *source = williams_videoram + y + 256 * (xoffset / 2);
  1375.             TYPE *dest;
  1376.  
  1377.             /* compute starting destination pixel based on flip */
  1378.             if (!(Machine->orientation & ORIENTATION_FLIP_Y))
  1379.                 dest = &((TYPE *)bitmap->line[y])[0];
  1380.             else
  1381.                 dest = &((TYPE *)bitmap->line[bitmap->height - 1 - y])[0];
  1382.  
  1383.             /* non-X-flipped case */
  1384.             if (!(Machine->orientation & ORIENTATION_FLIP_X))
  1385.             {
  1386.                 dest += xoffset;
  1387.                 for (x = 0; x < pairs; x++, source += 256, dest += 2)
  1388.                 {
  1389.                     int pix = *source;
  1390.                     if (pix)
  1391.                     {
  1392.                         int p1 = pix >> 4, p2 = pix & 0x0f;
  1393.                         if (p1) dest[0] = pens[p1];
  1394.                         if (p2) dest[1] = pens[p2];
  1395.                     }
  1396.                 }
  1397.             }
  1398.  
  1399.             /* X-flipped case */
  1400.             else
  1401.             {
  1402.                 dest += bitmap->width - xoffset;
  1403.                 for (x = 0; x < pairs; x++, source += 256, dest -= 2)
  1404.                 {
  1405.                     int pix = *source;
  1406.                     if (pix)
  1407.                     {
  1408.                         int p1 = pix >> 4, p2 = pix & 0x0f;
  1409.                         if (p1) dest[-1] = pens[p1];
  1410.                         if (p2) dest[-2] = pens[p2];
  1411.                     }
  1412.                 }
  1413.             }
  1414.         }
  1415.     }
  1416.  
  1417.     /* X/Y swapped case */
  1418.     else
  1419.     {
  1420.         int dy = (bitmap->line[1] - bitmap->line[0]) / sizeof(TYPE);
  1421.  
  1422.         /* loop over rows */
  1423.         for (y = clip->min_y; y <= clip->max_y; y++)
  1424.         {
  1425.             const UINT8 *source = williams_videoram + y + 256 * (xoffset / 2);
  1426.             TYPE *dest;
  1427.  
  1428.             /* compute starting destination pixel based on flip */
  1429.             if (!(Machine->orientation & ORIENTATION_FLIP_X))
  1430.                 dest = &((TYPE *)bitmap->line[0])[y];
  1431.             else
  1432.                 dest = &((TYPE *)bitmap->line[0])[bitmap->width - 1 - y];
  1433.  
  1434.             /* non-Y-flipped case */
  1435.             if (!(Machine->orientation & ORIENTATION_FLIP_Y))
  1436.             {
  1437.                 dest += xoffset * dy;
  1438.                 for (x = 0; x < pairs; x++, source += 256, dest += dy + dy)
  1439.                 {
  1440.                     int pix = *source;
  1441.                     if (pix)
  1442.                     {
  1443.                         int p1 = pix >> 4, p2 = pix & 0x0f;
  1444.                         if (p1) dest[0] = pens[p1];
  1445.                         if (p2) dest[dy] = pens[p2];
  1446.                     }
  1447.                 }
  1448.             }
  1449.  
  1450.             /* Y-flipped case */
  1451.             else
  1452.             {
  1453.                 dest += (bitmap->height - xoffset) * dy;
  1454.                 for (x = 0; x < pairs; x++, source += 256, dest -= dy + dy)
  1455.                 {
  1456.                     int pix = *source;
  1457.                     if (pix)
  1458.                     {
  1459.                         int p1 = pix >> 4, p2 = pix & 0x0f;
  1460.                         if (p1) dest[-dy] = pens[p1];
  1461.                         if (p2) dest[-dy-dy] = pens[p2];
  1462.                     }
  1463.                 }
  1464.             }
  1465.         }
  1466.     }
  1467. }
  1468.  
  1469.  
  1470. #endif
  1471.